import React, { useEffect, useMemo, useRef } from "react";
import { useRefCallback, udp, Skeleton, type IObject } from "@cscec/udp-ui";
import { setMasterOptions, getMasterOptions } from '@@/plugin-qiankun-master/masterOptions'
import { MicroApp } from "umi";

const defaultProps = {
    autoSetLoading: true,
    settings: {
        singular: false,
        sandbox: { experimentalStyleIsolation: true },
    },
    wrapperClassName: "udp-micro-app",
    className: "udp-micro-app",
    loader: (loading: any) => <Skeleton loading={loading} active style={{ padding: 24 }} />,
    autoCaptureError: true,
    errorBoundary: (error: {
        message:
        | string
        | number
        | boolean
        | React.ReactElement<any, string | React.JSXElementConstructor<any>>
        | React.ReactFragment
        | React.ReactPortal
        | null
        | undefined;
    }) => <div>Error: {error.message}</div>
};

export function MicroCmp(componentProps: { pathname: string; name: string; entry: string;[x: string]: any }) {
    const { pathname: url, entry, apiEntry = false, ...rest } = componentProps;
    const appName = componentProps.name;

    useMemo(() => {
        const { apps = [] } = getMasterOptions() as any;
        if (apps.find(app => app.name === appName)) {
            return;
        }
        setMasterOptions({
            apps: [...apps, {
                name: appName,
                credentials: false,
                entry,
                props: {
                    subRoot: '/',
                    appName,
                    basePath: `/${appName}`,
                    publicPath: ((url) => {
                        if (url.indexOf('//') === 0) {
                            url = window.location.protocol + url;
                        }
                        if (url[url.length - 1] === '/') {
                            return url;
                        }
                        return url.match(/^http[s]?:\/\/(.)+\//)?.[0] || `${url.replace('/index.html', '')}/`;
                    })(entry),
                    createPath(microAppPath: string, query?: IObject) {
                        return udp.handleUrl(`#/${appName}${microAppPath.startsWith('/') ? '' : '/'}${microAppPath}`, {
                            ...udp.getQueryValue(''),
                            ...query
                        });
                    },
                    getMasterInfo() {
                        const getRoot = () => {
                            if (apiEntry) {
                                let _root = udp.isString(apiEntry) ? apiEntry : entry[entry.length - 1] === '/' ? entry : `${entry}/`;
                                if (entry.indexOf('//') === 0) {
                                    _root = window.location.protocol + _root;
                                }
                                return _root.match(/^http[s]?:\/\/([^\/])+\//)?.[0] || '/';
                            }
                            return udp.getRoot();
                        };
                        return {
                            getUser() {
                                return { ...udp.getUser(), root: getRoot() };
                            },
                            getObserver() {
                                return udp.getObserver();
                            }
                        };
                    }
                }
            }]
        });
    }, [appName, entry]);

    const history = useRef<any>();
    // url 的变更不会透传给下游，组件内自己会处理掉，所以这里直接用 ref 来存
    const historyOpts = useRef({
        type: 'memory',
        initialEntries: [url],
        initialIndex: 1,
    });

    const historyInitHandler = useRefCallback((h) => {
        // 重写push很关键，让push通过父应用来统一控制
        h.push = (path, query) => {
            udp.open(path, { microAppName: componentProps.name, ...query });
        };
        history.current = h;
    });

    useEffect(() => {
        // push history for slave app when url property changed
        // the initial url will be ignored because the history has not been initialized
        if (history.current && url) {
            history.current.push(url);
        }
    }, [url]);

    useEffect(() => {
        // reset the history when name changed
        historyOpts.current.initialEntries = [url];
        historyOpts.current.initialIndex = 1;
    }, [componentProps.name]);

    return (
        <MicroApp
            {...defaultProps}
            {...rest}
            history={historyOpts.current}
            onHistoryInit={historyInitHandler}
        />
    );
}
